Skip to content

Atomic + permission-safe self-update (TIGER-225) - #309

Open
WebTigers wants to merge 1 commit into
mainfrom
feat/atomic-composer-update
Open

WebTigers wants to merge 1 commit into
mainfrom
feat/atomic-composer-update

Conversation

@WebTigers

Copy link
Copy Markdown
Owner

Why

A web-driven core update that failed part-way white-screened a panel (host1, 2026-09-24): Composer, running as apache, couldn't delete a vendor/ file owned by another user and aborted mid-extract, leaving vendor/webtigers/tiger-core half-removed (functions.php gone) → fatal on autoload → every request 500.

Root cause is tool-independent: the update mutated vendor/ in place with no rollback, and the preflight only checked is_writable(vendor) (the top dir), missing a nested dir the web user didn't own.

What

Tiger_Update_Composer::update() is now atomic and fails clean:

  • Deep writability preflight — walk the whole vendor tree; abort before any change if the web user can't replace a nested dir, naming it + a fix command.
  • Stage aside before Composer — rename the target package to var/update-rollback-* first. That's the rollback point, and it removes the failure mode (Composer does a clean fresh install with nothing to delete).
  • Restore-on-failure — if Composer errors, or "succeeds" but the package is missing/incomplete (tiger-core needs Version.php + functions.php), the previous version is moved back. A failed update never breaks the site.

Version → 1.15.1, CHANGELOG updated. 4 new unit tests (deep preflight, intact check, restore); 11 pass.

Follow-up

The full release-swap model (pre-vendored bundle + symlink flip; never run Composer on a live box) stays the longer-term direction in TIGER-225 — this hardens the in-place path meanwhile.

🤖 Generated with Claude Code

https://claude.ai/code/session_01ASauLLscjqdsNqBNsx2Typ

A web-driven core update that failed part-way white-screened a panel: Composer,
running as apache, could not delete a vendor file owned by another user and
aborted mid-extract, leaving vendor/webtigers/tiger-core half-removed
(functions.php gone) -> fatal on autoload -> every request 500.

Tiger_Update_Composer::update() is now atomic and fails clean:
- DEEP writability preflight: walk the whole vendor tree (is_writable only
  checked the top dir before) and abort BEFORE any change if the web user can't
  replace a nested dir, naming it + a fix command. Deletion needs write on the
  containing dir, so we test dirs.
- Stage the target package ASIDE (rename to var/update-rollback-*) before
  Composer runs. This is the rollback point AND removes the failure mode: with
  the old dir gone, Composer does a clean fresh install with nothing to delete.
- Restore-on-failure: if Composer errors, or "succeeds" but the package is
  missing/incomplete (tiger-core must have Version.php + functions.php), move the
  previous version back. A failed update never leaves the site broken.

Version 1.15.1; CHANGELOG. 4 new unit tests for the deep preflight, the intact
check, and restore (11 pass). Note: the full release-swap distribution model
(pre-vendored bundle + symlink flip; never run Composer on a live box) remains
the longer-term direction in TIGER-225; this hardens the in-place path meanwhile.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ASauLLscjqdsNqBNsx2Typ
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant